package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zzyl.base.PageResponse;
import com.zzyl.constant.DeviceCacheConstant;
import com.zzyl.dto.*;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.enums.LocationTypeEnum;
import com.zzyl.enums.PhysicalLocationTypeEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIotConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DeviceServiceImpl implements DeviceService {
    @Autowired
    private AliIotConfigProperties aliIotConfigProperties;
    @Autowired
    private Client client;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private DeviceMapper deviceMapper;

    @Override
    public void syncProductList() {

        QueryProductListRequest queryProductListRequest = new QueryProductListRequest();
        //分页条件
        queryProductListRequest.setPageSize(10);
        queryProductListRequest.setCurrentPage(1);
        //公共实例
        queryProductListRequest.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        try {
            //查询公共实例下的所有产品
            QueryProductListResponse queryProductListResponse = client.queryProductList(queryProductListRequest);
            if (queryProductListResponse.getBody().success) {
                // 解析响应结果
                List<QueryProductListResponseBody.QueryProductListResponseBodyDataListProductInfo> productInfo = queryProductListResponse.getBody().getData().getList().getProductInfo();
                // 保存到redis
                stringRedisTemplate.opsForValue().set(DeviceCacheConstant.DEVICE_LIST, JSONUtil.toJsonStr(productInfo));
            } else {
                throw new BaseException(BasicEnum.IOT_QUERY_PRODUCT_ERROR);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }
    }

    @Override
    public List<ProductVo> allProduct() {
        String s = stringRedisTemplate.opsForValue().get(DeviceCacheConstant.DEVICE_LIST);
        if (Objects.isNull(s)) {
            return new ArrayList<>();
        }
        return JSONUtil.toList(s, ProductVo.class);
    }

    @Override
    public void registerDevice(DeviceDto dto) {
        // 判断重名
        Device deviceDB = deviceMapper.selectByName(dto.getDeviceName());
        if (deviceDB != null) {
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }
        // 保存到阿里云
        RegisterDeviceResponse response = null;
        RegisterDeviceRequest request = dto.getRegisterDeviceRequest();
        request.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        try {
            response = client.registerDevice(request);
            if (!response.getBody().success) {
                log.error("注册设备失败：{}", response.getBody().getErrorMessage());
                throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
        // 保存到mysql
        String iotId = response.getBody().getData().getIotId();
        Device device = BeanUtil.copyProperties(dto, Device.class);
        device.setIotId(iotId);
        if (LocationTypeEnum.PORTABLE_DEVICE.getValue() == dto.getLocationType()) {
            device.setPhysicalLocationType(PhysicalLocationTypeEnum.ELDER.getValue());
        }
        //删除设备
        try{
            deviceMapper.insertSelective(device);
        }catch (Exception e){
            log.error(e.getMessage(), e);
            // 把设备从阿里云再删除
            DeleteDeviceRequest deleteRequest = new DeleteDeviceRequest();
            deleteRequest.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
            deleteRequest.setProductKey(dto.getProductKey());
            deleteRequest.setDeviceName(dto.getDeviceName());
            deleteRequest.setIotId(iotId);
            try{
                DeleteDeviceResponse deleteResponse = client.deleteDevice(deleteRequest);
                if(!deleteResponse.getBody().success){
                    log.error("删除设备失败：{}", response.getBody().getErrorMessage());
                    throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
                }
            }catch(Exception ex){
                log.error(ex.getMessage(), ex);
                throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
            }
        }
    }

    @Override
    public PageResponse<DeviceVo> pageQueryDevice(DevicePageQueryDto dto) {
        PageHelper.startPage(dto.getPageNum(),dto.getPageSize());
        Page<DeviceVo> deviceVos =  deviceMapper.pageQueryDevice(dto);
        return PageResponse.of(deviceVos,DeviceVo.class);
    }

    @Override
    public DeviceVo queryDeviceDetail(QueryDeviceDto dto) {
        //准备返回的数据
        DeviceVo deviceVo = new DeviceVo();
        //从数据库查数据
        Device device = deviceMapper.queryDeviceDetailByIotId(dto.getIotId());
        if(Objects.isNull(device)){
            throw new BaseException(BasicEnum.DATA_NOT_EXIST);
        }
        //第一次拷贝
        BeanUtil.copyProperties(device,deviceVo);
        //从阿里云查数据
        QueryDeviceDetailRequest deviceDetailRequest = new QueryDeviceDetailRequest();
        deviceDetailRequest.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        deviceDetailRequest.setProductKey(device.getProductKey());
        deviceDetailRequest.setDeviceName(device.getDeviceName());
        deviceDetailRequest.setIotId(device.getIotId());
        try {
            QueryDeviceDetailResponse queryDeviceDetail = client.queryDeviceDetail(deviceDetailRequest);
            if (queryDeviceDetail.getBody().success) {
                QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData data = queryDeviceDetail.getBody().getData();
                //第二次拷贝数据，这次需要设置忽略空值
                BeanUtil.copyProperties(data,deviceVo,new CopyOptions().ignoreNullValue());
            }else {
                log.error("阿里云查询设备详情异常：{}", queryDeviceDetail.getBody().getErrorMessage());
                throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
            }

        } catch (Exception e) {
            log.error("查询设备详情异常：{}",e.getMessage(),e);
            throw new BaseException(BasicEnum.QUERY_DEVICE_DETAIL_ERROR);
        }
        return deviceVo;
    }

    @Override
    public QueryThingModelVo queryThingModelPublished(QueryThingModelDto dto) {
        QueryThingModelPublishedRequest request = new QueryThingModelPublishedRequest();
        request.setProductKey(dto.getProductKey());
        request.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        String thingModelJson=null;
        try {
            QueryThingModelPublishedResponse response = client.queryThingModelPublished(request);
            if (response.getBody().success) {
                thingModelJson = response.getBody().getData().getThingModelJson();
            }
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }
        return new QueryThingModelVo(thingModelJson);
    }

    @Override
    public void updateDevice(DeviceDto dto) {
        //更新阿里云
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        request.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        List<BatchUpdateDeviceNicknameRequest. BatchUpdateDeviceNicknameRequestDeviceNicknameInfo> deviceNicknameInfo = new ArrayList<>();
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo info = new BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo();
        info.setDeviceName(dto.getDeviceName());
        info.setIotId(dto.getIotId());
        info.setProductKey(dto.getProductKey());
        info.setNickname(dto.getNickname());
        deviceNicknameInfo.add(info);
        request.setDeviceNicknameInfo(deviceNicknameInfo);
        try {
            BatchUpdateDeviceNicknameResponse response = client.batchUpdateDeviceNickname(request);
            if (response.getBody().success) {
                //阿里云更新成功后更新数据库
                Device device = BeanUtil.copyProperties(dto, Device.class);
                deviceMapper.updateByPrimaryKeySelective(device);
            }
        } catch (Exception e) {
            log.error("阿里云更新设备名称失败：{}",e.getMessage(), e);
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }
    }
    @Override
    public void deleteDevice(DeleteDeviceDto dto) {
        //阿里云删除时需要设备名，先查一下设备名
        String deviceName = deviceMapper.getDeviceNameByIotId(dto.getIotId());
        //先删除阿里云
        DeleteDeviceRequest request = new DeleteDeviceRequest();
        request.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        request.setProductKey(dto.getProductKey());
        request.setDeviceName(deviceName);
        try {
            DeleteDeviceResponse deleteDeviceResponse = client.deleteDevice(request);
            if(deleteDeviceResponse.getBody().success){
                //阿里云删除成功后删库
                deviceMapper.deleteDeviceByIotId(dto.getIotId());
                log.info("删除设备成功");
            }
        } catch (Exception e) {
            log.error("阿里云接口删除设备失败：{}",e.getMessage(), e);
            throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
        }
    }

    @Override
    public DevicePropertyStatusVo queryDevicePropertyStatus(DevicePropertyStatusDto dto) {
        QueryDevicePropertyStatusRequest request = new QueryDevicePropertyStatusRequest();
        request.setIotInstanceId(aliIotConfigProperties.getIotInstanceId());
        request.setProductKey(dto.getProductKey());
        request.setDeviceName(dto.getDeviceName());
        List<PropertyStatusInfo> devicePropertyStatusVoList;
        try {
            QueryDevicePropertyStatusResponse response = client.queryDevicePropertyStatus(request);
            List<QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyDataListPropertyStatusInfo> propertyStatusInfo = response.getBody().getData().getList().getPropertyStatusInfo();
            devicePropertyStatusVoList = propertyStatusInfo.stream().map(info -> BeanUtil.copyProperties(info, PropertyStatusInfo.class)).collect(Collectors.toList());
        } catch (Exception e) {
            log.error("阿里云查询设备的物模型运行状态失败：{}",e.getMessage(), e);
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }
        return new DevicePropertyStatusVo(devicePropertyStatusVoList);
    }
}
